#pragma once
#include "HashTable.h"
using namespace::HashBucket_;
namespace m_underodermap
{
	template<class K, class V, class Hash = HashFunc<K>>
	class unordermap
	{
	public:

	private:
		HashBucket<K,V,Hash> hashtable;
	};
}

namespace m_unorderset
{
	template<class K >
	class HashNode
	{
	public:
		HashNode<K>* next = nullptr;
		K _data;
	};

	template<class K>
	struct HashFunc
	{
		int operator()(const K& k)
		{
			return k;
		}
	};

	template<>
	struct HashFunc<string>
	{
		size_t operator()(const string& str)
		{
			register size_t hash = 0;

			for (auto& e : str)
			{
				hash += e;
				hash *= 31;
			}

			return hash;
		}
	};

	template<class K,class HashF = HashFunc<K>>
	class HashBucket
	{
		typedef HashNode<K> node;
	public:
		bool insert(const K& template<class K, class V >
	class HashNode
	{
	public:
		HashNode<K, V>* next = nullptr;
		pair<K, V> _data;
	};

	template<class K>
	struct HashFunc
	{
		int operator()(const K& k)
		{
			return k;
		}
	};

	template<>
	struct HashFunc<string>
	{
		size_t operator()(const string& str)
		{
			register size_t hash = 0;

			for (auto& e : str)
			{
				hash += e;
				hash *= 31;
			}

			return hash;
		}
	};

	template<class K, class V, class HashF = HashFunc<K>>
	class HashBucket
	{
		typedef HashNode<K, V> node;
	public:
		bool insert(const pair<K, V>& kv)
		{
			if (tables.size() == 0 || (_n * 10 / tables.size() >= 7))
			{
				int newsize = _n == 0 ? 10 : tables.size() * 2;
				HashBucket newhash;
				newhash.tables.resize(newsize);

				for (int i = 0; i < tables.size(); i++)
				{
					node*& temp = tables[i];
					while (temp)
					{
						node* temp_next = temp->next;
						//newhash.insert(make_pair(temp->next->_data.first, temp->next->_data.first));
						int newindex = HashF()(temp->_data.first) % newsize;
						temp->next = newhash.tables[newindex];

						newhash.tables[newindex] = temp;

						temp = temp_next;

					}
				}

				newhash.tables.swap(tables);
			}

			int index = HashF()(kv.first) % tables.size();
			node* newnode = new node;
			newnode->_data = kv;
			newnode->next = tables[index];
			tables[index] = newnode;

			_n++;

			return true;
		}
		bool erase(const K& k)
		{
			int index = HashF(k) % tables.size();
			node* cur = tables[index];
			node* prev = nullptr;
			while (cur)
			{
				if (cur->_data.first == k && cur == tables[index])
				{
					tables[index] = cur->next;
					_n--;
					return true;
				}
				else if (cur->_data.first == k)
				{
					prev->next = cur->next;
					delete cur;
					cur = nullptr;
					_n--;
					return true;
				}
				prev = cur;
				cur = cur->next;
			}

			return false;
		}
		~HashBucket()
		{
			;
		}
	private:
		vector<node*> tables;
		size_t _n = 0;
	};)
		{
			if (tables.size() == 0 || (_n * 10 / tables.size() >= 7))
			{
				int newsize = _n == 0 ? 10 : tables.size() * 2;
				HashBucket newhash;
				newhash.tables.resize(newsize);

				for (int i = 0; i < tables.size(); i++)
				{
					node*& temp = tables[i];
					while (temp)
					{
						node* temp_next = temp->next;
						//newhash.insert(make_pair(temp->next->_data.first, temp->next->_data.first));
						int newindex = HashF()(temp->_data.first) % newsize;
						temp->next = newhash.tables[newindex];

						newhash.tables[newindex] = temp;

						temp = temp_next;

					}
				}

				newhash.tables.swap(tables);
			}

			int index = HashF()(kv) % tables.size();
			node* newnode = new node;
			newnode->_data = kv;
			newnode->next = tables[index];
			tables[index] = newnode;

			_n++;

			return true;
		}
		bool erase(const K& k)
		{
			int index = HashF(k) % tables.size();
			node* cur = tables[index];
			node* prev = nullptr;
			while (cur)
			{
				if (cur->_data.first == k && cur == tables[index])
				{
					tables[index] = cur->next;
					_n--;
					return true;
				}
				else if (cur->_data.first == k)
				{
					prev->next = cur->next;
					delete cur;
					cur = nullptr;
					_n--;
					return true;
				}
				prev = cur;
				cur = cur->next;
			}

			return false;
		}
		~HashBucket()
		{
			;
		}
	private:
		vector<node*> tables;
		size_t _n = 0;
	};
	template<class K, class Hash = HashFunc<K>>
	class unordermap
	{
	public:

	private:
		HashBucket<K, Hash> hashtable;
	};
}